import { inject, onMounted, ref, Ref, toRef, watch } from 'vue';

/**
 * 处理表单组件v-model绑定的组合式函数
 * 使用toRef获取指定属性的引用并创建本地副本
 * @param {Record<string, any>} props 组件的props对象
 * @param {K} propName 可选，v-model绑定的属性名，默认为'modelValue'
 * @returns 本地值引用
 */
export function useModelValue<
  T = any,
  K extends string = string,
  P extends Record<K, T> = Record<K, T>
>(
  props: P,
  propName: K = 'modelValue' as K
): Ref<T> {
  // 获取指定属性的ref
  const modelValueRef = toRef(props, propName);

  // 创建本地value副本用于v-model
  const localValue = ref(modelValueRef.value);

  // 监听props中modelValue的变化，同步到本地value
  watch(modelValueRef, (newValue) => {
    localValue.value = newValue;
  });

  return localValue;
};



/**
 * 表单字段注册的组合式函数
 * 用于封装表单组件中字段注册的通用逻辑
 * @param {string} fieldName 字段名称
 */
export function useRegisterField(fieldName: string) {
  // 通过依赖注入获取字段注册方法
  const registerFieldName = inject<(name: string) => void>('registerFieldName');

  // 注册字段名的函数
  const register = (name: string) => {
    if (registerFieldName && name) {
      registerFieldName(name);
    }
  };

  // 在组件挂载时注册字段名
  onMounted(() => register(fieldName));

  // 监听字段名变化，重新注册
  watch(() => fieldName, register);
};

/**
 * 处理表单组件formItemId的组合式函数
 * 用于获取表单项目的唯一标识符
 * @param {Record<string, any>} props 组件的props对象
 * @param {string} propIdName 可选，props中id属性的名称，默认为'id'
 * @returns {Ref<string>} formItemId的引用
 */
export function useFormItemId(
  props: Record<string, any>,
  propIdName: string = 'id'
): Ref<string> {
  // 获取props中的id属性值
  const idFromProps = props[propIdName] || '';

  // 优先使用props中的id，否则使用注入的formItemId
  const formItemId = ref(idFromProps || inject('formItemId', ''));

  return formItemId;
};

/**
 * 处理表单字段验证的组合式函数
 * 用于获取字段验证方法
 * @param {string} injectKey 可选，注入的验证方法键名，默认为'validateField'
 * @returns {(field: string, value: any) => string[]} 验证函数，返回验证错误信息数组
 */
export function useValidateField(
  injectKey: string = 'validateField'
): (field: string, value: any) => string[] {
  // 通过依赖注入获取验证方法
  const validateMethod = inject<(field: string, value: any) => string[]>(injectKey);
  
  // 如果没有注入验证方法，返回一个空数组的默认函数
  return validateMethod || (() => []);
};
